/**
 * @file
 *   @brief Map Tile Cache
 *
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

#ifndef QGC_MAP_ENGINE_H
#define QGC_MAP_ENGINE_H

#include <QString>

#include "QGCMapUrlEngine.h"
#include "QGCMapEngineData.h"
#include "QGCTileCacheWorker.h"


//-----------------------------------------------------------------------------
/**
 * @brief QGC地图引擎类
 * 
 * QGCMapEngine是QGroundControl的地图引擎核心类，负责管理地图瓦片的缓存、
 * 加载和存储。它是整个地图系统的核心，协调地图数据的获取、存储和检索。
 * 
 * 主要功能包括：
 * 1. 地图瓦片缓存管理 - 管理本地磁盘和内存中的地图瓦片缓存
 * 2. 地图任务调度 - 通过工作线程处理地图相关的异步任务
 * 3. 地图数据存储 - 将下载的地图瓦片存储到本地数据库
 * 4. 地图提供商管理 - 通过UrlFactory管理不同类型的地图提供商
 * 5. 缓存策略控制 - 控制磁盘和内存缓存的大小限制
 * 6. 网络状态检测 - 检测网络连接状态以优化地图加载策略
 * 7. 瓦片计算功能 - 提供瓦片坐标计算、哈希生成等工具函数
 */
class QGCMapEngine : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief 构造函数
     * 初始化地图引擎，创建URL工厂和设置默认参数
     */
    QGCMapEngine                ();
    
    /**
     * @brief 析构函数
     * 清理地图引擎资源，包括工作线程和URL工厂
     */
    ~QGCMapEngine               ();

    /**
     * @brief 初始化地图引擎
     * 设置缓存路径，初始化数据库并启动工作线程
     */
    void                        init                ();
    
    /**
     * @brief 添加地图任务到队列
     * @param task 要执行的地图任务对象指针
     */
    void                        addTask             (QGCMapTask *task);
    
    /**
     * @brief 缓存地图瓦片（通过坐标）
     * @param type 地图类型
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param z 缩放级别
     * @param image 瓦片图像数据
     * @param format 图像格式
     * @param set 瓦片集ID，默认为UINT64_MAX
     */
    void                        cacheTile           (const QString& type, int x, int y, int z, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
    
    /**
     * @brief 缓存地图瓦片（通过哈希）
     * @param type 地图类型
     * @param hash 瓦片哈希值
     * @param image 瓦片图像数据
     * @param format 图像格式
     * @param set 瓦片集ID，默认为UINT64_MAX
     */
    void                        cacheTile           (const QString& type, const QString& hash, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
    
    /**
     * @brief 创建获取瓦片任务
     * @param type 地图类型
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param z 缩放级别
     * @return QGCFetchTileTask* 获取瓦片任务对象指针
     */
    QGCFetchTileTask*           createFetchTileTask (const QString& type, int x, int y, int z);
    
    /**
     * @brief 获取地图名称列表
     * @return QStringList 支持的地图类型名称列表
     */
    QStringList                 getMapNameList      ();
    
    /**
     * @brief 获取用户代理字符串
     * @return const QString& 当前设置的用户代理字符串
     */
    const QString               userAgent           () { return _userAgent; }
    
    /**
     * @brief 设置用户代理字符串
     * @param ua 用户代理字符串
     */
    void                        setUserAgent        (const QString& ua) { _userAgent = ua; }
    
    /**
     * @brief 根据哈希值获取地图类型
     * @param hash 瓦片哈希值
     * @return QString 地图类型名称
     */
    QString                     hashToType          (const QString& hash);
    
    /**
     * @brief 获取最大磁盘缓存大小
     * @return quint32 最大磁盘缓存大小（MB）
     */
    quint32                     getMaxDiskCache     ();
    
    /**
     * @brief 设置最大磁盘缓存大小
     * @param size 最大磁盘缓存大小（MB）
     */
    void                        setMaxDiskCache     (quint32 size);
    
    /**
     * @brief 获取最大内存缓存大小
     * @return quint32 最大内存缓存大小（MB）
     */
    quint32                     getMaxMemCache      ();
    
    /**
     * @brief 设置最大内存缓存大小
     * @param size 最大内存缓存大小（MB）
     */
    void                        setMaxMemCache      (quint32 size);
    
    /**
     * @brief 获取缓存路径
     * @return const QString 缓存目录路径
     */
    const QString               getCachePath        () { return _cachePath; }
    
    /**
     * @brief 获取缓存文件名
     * @return const QString 缓存数据库文件名
     */
    const QString               getCacheFilename    () { return _cacheFile; }
    
    /**
     * @brief 测试网络连接状态
     */
    void                        testInternet        ();
    
    /**
     * @brief 检查缓存是否被重置
     * @return bool 缓存是否被重置
     */
    bool                        wasCacheReset       () const{ return _cacheWasReset; }
    
    /**
     * @brief 检查网络是否活跃
     * @return bool 网络是否活跃
     */
    bool                        isInternetActive    () const{ return _isInternetActive; }

    /**
     * @brief 获取URL工厂实例
     * @return UrlFactory* URL工厂对象指针
     */
    UrlFactory*                 urlFactory          () { return _urlFactory; }

    //-- Tile Math
    /**
     * @brief 计算指定区域的瓦片数量
     * @param zoom 缩放级别
     * @param topleftLon 左上角经度
     * @param topleftLat 左上角纬度
     * @param bottomRightLon 右下角经度
     * @param bottomRightLat 右下角纬度
     * @param mapType 地图类型
     * @return QGCTileSet 瓦片集信息
     */
    static QGCTileSet           getTileCount        (int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, const QString& mapType);
    
    /**
     * @brief 生成瓦片哈希值
     * @param type 地图类型
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param z 缩放级别
     * @return QString 瓦片哈希值
     */
    static QString              getTileHash         (const QString& type, int x, int y, int z);
    
    /**
     * @brief 根据名称获取地图类型
     * @param name 地图名称
     * @return QString 地图类型
     */
    static QString              getTypeFromName     (const QString& name);
    
    /**
     * @brief 将大数字转换为带单位的字符串
     * @param size 大小值
     * @return QString 带单位的大小字符串
     */
    static QString              bigSizeToString     (quint64 size);
    
    /**
     * @brief 将存储空间大小转换为带单位的字符串
     * @param size_MB 存储空间大小（MB）
     * @return QString 带单位的存储空间大小字符串
     */
    static QString              storageFreeSizeToString(quint64 size_MB);
    
    /**
     * @brief 将数字转换为本地化字符串
     * @param number 数字值
     * @return QString 本地化数字字符串
     */
    static QString              numberToString      (quint64 number);
    
    /**
     * @brief 获取并发下载数
     * @param type 地图类型
     * @return int 并发下载数
     */
    static int                  concurrentDownloads (const QString& type);

private slots:
    /**
     * @brief 更新缓存统计信息
     * @param totaltiles 总瓦片数
     * @param totalsize 总大小
     * @param defaulttiles 默认瓦片数
     * @param defaultsize 默认大小
     */
    void _updateTotals          (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
    
    /**
     * @brief 缓存清理完成回调
     */
    void _pruned                ();
    
    /**
     * @brief 网络状态更新回调
     * @param active 网络是否活跃
     */
    void _internetStatus        (bool active);

signals:
    /**
     * @brief 缓存统计信息更新信号
     * @param totaltiles 总瓦片数
     * @param totalsize 总大小
     * @param defaulttiles 默认瓦片数
     * @param defaultsize 默认大小
     */
    void updateTotals           (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
    
    /**
     * @brief 网络状态更新信号
     */
    void internetUpdated        ();

private:
    /**
     * @brief 清理旧缓存目录
     */
    void _wipeOldCaches         ();
    
    /**
     * @brief 检查并清理指定目录
     * @param dirPath 目录路径
     */
    void _checkWipeDirectory    (const QString& dirPath);
    
    /**
     * @brief 递归删除目录及其内容
     * @param dirPath 目录路径
     * @return bool 删除是否成功
     */
    bool _wipeDirectory         (const QString& dirPath);

private:
    QGCCacheWorker          _worker;              ///< 缓存工作线程，负责处理地图瓦片的异步操作
    QString                 _cachePath;           ///< 缓存目录路径
    QString                 _cacheFile;           ///< 缓存数据库文件名
    UrlFactory*             _urlFactory;          ///< URL工厂，用于生成不同地图提供商的URL
    QString                 _userAgent;           ///< 用户代理字符串，用于HTTP请求头
    quint32                 _maxDiskCache;        ///< 最大磁盘缓存大小（MB）
    quint32                 _maxMemCache;         ///< 最大内存缓存大小（MB）
    bool                    _prunning;            ///< 是否正在进行缓存清理
    bool                    _cacheWasReset;       ///< 缓存是否被重置
    bool                    _isInternetActive;    ///< 网络是否活跃
};

/**
 * @brief 获取QGC地图引擎单例实例
 * @return QGCMapEngine* 地图引擎实例指针
 */
extern QGCMapEngine*    getQGCMapEngine();

/**
 * @brief 销毁QGC地图引擎单例实例
 */
extern void             destroyMapEngine();

#endif // QGC_MAP_ENGINE_H